#include "config.h"
#include "ecm.h"

#ifndef _WIN32

#include <readline/readline.h>
#include <readline/history.h>

static ecm_readline_mode_t	ecm_readline_mode;

static void
inthandler(int signo)
{
 	rl_delete_text(0, rl_end);
 	rl_point = 0;
 	rl_redisplay();
}

char *
ecm_readline(const char *prompt)
{
	static ECMBOOL	initialized = ECM_FALSE;
	char	*line, *res;
	struct	sigaction	sigact, oldact;

	if (!initialized) {
		using_history();
		initialized = ECM_TRUE;
	}

	rl_already_prompted = 0;

 	sigact.sa_handler = inthandler;
 	sigact.sa_flags = 0;
 	sigemptyset(&sigact.sa_mask);
 	sigaction(SIGINT, &sigact, &oldact);

	line = readline(prompt);

	sigaction(SIGINT, &oldact, NULL);
	if (line && ecm_readline_mode == ECM_READLINE_ECHO)
		add_history(line);
	res = ecm_strdup(line);
	free(line);
	return res;
}

static void
redisplay_noecho(void)
{
	if (rl_already_prompted == 0) {
		fprintf(rl_outstream, "%s", rl_prompt);
		fflush(rl_outstream);
		rl_already_prompted = 1;
	}
}

void
ecm_readline_setmode(ecm_readline_mode_t mode)
{
	ecm_readline_mode = mode;
	switch (mode) {
	case ECM_READLINE_ECHO:
		rl_redisplay_function = rl_redisplay;
		break;
	case ECM_READLINE_NOECHO:
		rl_redisplay_function = redisplay_noecho;
		break;
	}
}

#else

#include <windows.h>

static ECMBOOL echoDisabled;

char *
ecm_readline(const char *prompt)
{
	char	buf[1024];
	int	nRead;
	HANDLE	hInput = GetStdHandle(STD_INPUT_HANDLE);
	HANDLE	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	DWORD	mode_org, mode;
	DWORD	nWritten;

	GetConsoleMode(hInput, &mode_org);
	if (!ecm_empty_str(prompt)) {
		WriteConsole(hOutput, prompt, ecm_strlen(prompt), &nWritten, NULL);
	}
	
	mode = mode_org;
	if (echoDisabled)
		mode &= ~ENABLE_ECHO_INPUT;
	else
		mode |= ENABLE_ECHO_INPUT;
	SetConsoleMode(hInput, mode);
	if (!ReadConsole(hInput, buf, sizeof(buf), &nRead, NULL)) {
		SetConsoleMode(hInput, mode_org);
		return NULL;
	}
	SetConsoleMode(hInput, mode_org);
	WriteConsole(hOutput, "\n", 1, &nWritten, NULL);

	if (nRead < 2)
		buf[0] = '\0';
	else
		buf[nRead - 2] = '\0';
	return ecm_strdup(buf);
}

void
ecm_readline_setmode(ecm_readline_mode_t mode)
{
	if (mode == ECM_READLINE_ECHO)
		echoDisabled = ECM_FALSE;
	else if (mode == ECM_READLINE_NOECHO)
		echoDisabled = ECM_TRUE;
}

#endif
